// File: jmcomic-core/src/main/java/dev/jukomu/common/postman/Postman.java
package dev.jukomu.common.postman;

import dev.jukomu.common.util.net.IResponse;

import java.util.Map;

/**
 * 对应Python的Postman，定义了HTTP请求的抽象接口。
 */
public interface Postman {

    /**
     * 发送HTTP GET请求。
     *
     * @param url    请求URL
     * @param kwargs 可变参数Map，包含data, json, params, headers, cookies, files, auth, timeout, allow_redirects, proxies, hooks, stream, verify, cert等
     * @return 响应对象IResponse
     * @throws Exception 任何可能发生的请求异常
     */
    IResponse get(String url, Map<String, Object> kwargs) throws Exception;

    /**
     * 发送HTTP GET请求，不带额外参数。
     *
     * @param url 请求URL
     * @return 响应对象IResponse
     * @throws Exception 任何可能发生的请求异常
     */
    default IResponse get(String url) throws Exception {
        return get(url, null);
    }

    /**
     * 发送HTTP POST请求。
     *
     * @param url    请求URL
     * @param kwargs 可变参数Map，包含data, json, params, headers, cookies, files, auth, timeout, allow_redirects, proxies, hooks, stream, verify, cert等
     * @return 响应对象IResponse
     * @throws Exception 任何可能发生的请求异常
     */
    IResponse post(String url, Map<String, Object> kwargs) throws Exception;

    /**
     * 发送HTTP POST请求，不带额外参数。
     *
     * @param url 请求URL
     * @return 响应对象IResponse
     * @throws Exception 任何可能发生的请求异常
     */
    default IResponse post(String url) throws Exception {
        return post(url, null);
    }

    /**
     * 创建当前Postman实例的一个副本。
     *
     * @return Postman副本
     */
    Postman copy();

    /**
     * 获取Postman的元数据。
     *
     * @param key          元数据键（可选），如果为null则返回所有元数据Map
     * @param defaultValue 默认值，当键不存在时的默认值
     * @param <T>          返回类型
     * @return 元数据值或默认值
     */
    <T> T getMetaData(String key, T defaultValue);

    /**
     * 获取所有元数据Map。
     *
     * @return 元数据Map
     */
    Map<String, Object> getMetaData();

    /**
     * 获取指定键的元数据值。
     *
     * @param key 元数据键
     * @return 元数据值
     * @throws java.util.NoSuchElementException 如果键不存在
     */
    default Object getMetaData(String key) {
        return getMetaData(key, null); // Allow null for non-existent keys, consistent with Map.get()
    }

    /**
     * 获取指定键的元数据值，如果键不存在则抛出异常。
     * 对应Python的__getitem__。
     *
     * @param key 键
     * @return 元数据值
     * @throws java.util.NoSuchElementException 如果键不存在
     */
    default Object getItem(String key) {
        if (!getMetaData().containsKey(key)) {
            throw new java.util.NoSuchElementException("Key not found in Postman metaData: " + key);
        }
        return getMetaData().get(key);
    }

    /**
     * 设置元数据值。
     * 对应Python的__setitem__。
     *
     * @param key   键
     * @param value 值
     */
    void setItem(String key, Object value);

    /**
     * 创建一个Postman实例。
     *
     * @param clazz  Postman实现类（可选，如果为null则使用默认实现）
     * @param kwargs 初始化参数Map
     * @return Postman实例
     */
    static Postman create(Class<? extends Postman> clazz, Map<String, Object> kwargs) {
        // 这里的默认实现依赖postman.impl包，将在该包完成后填充
        throw new UnsupportedOperationException("Default Postman.create implementation depends on PostmanImpl, not yet implemented.");
    }

    /**
     * 获取最底层的原始Postman实例（用于代理链）。
     *
     * @return 原始Postman实例
     */
    Postman getRootPostman();

    // --- 代理方法链式调用 ---

    /**
     * 返回一个带有固定URL的Postman代理。
     *
     * @param url 固定URL
     * @return Postman代理
     */
    Postman withFixUrl(String url);

    /**
     * 返回一个带有重试功能的Postman代理。
     *
     * @param retryTimes 重试次数
     * @param clazz      重试代理实现类（可选）
     * @return Postman代理
     */
    Postman withRetry(int retryTimes, Class<? extends Postman> clazz);

    /**
     * 返回一个带有重试功能的Postman代理，使用默认实现类。
     *
     * @param retryTimes 重试次数
     * @return Postman代理
     */
    default Postman withRetry(int retryTimes) {
        return withRetry(retryTimes, null);
    }

    /**
     * 返回一个支持Multipart请求的Postman代理。
     *
     * @return Postman代理
     */
    Postman withMultiPart();

    /**
     * 返回一个包装响应的Postman代理。
     *
     * @param clazz 响应包装类（可选）
     * @return Postman代理
     */
    Postman withWrapResp(Class<? extends IResponse> clazz);

    /**
     * 返回一个包装响应的Postman代理，使用默认实现类。
     *
     * @return Postman代理
     */
    default Postman withWrapResp() {
        return withWrapResp(null);
    }

    /**
     * 返回一个捕获重定向的Postman代理。
     *
     * @param clazz 重定向代理实现类（可选）
     * @return Postman代理
     */
    Postman withRedirectCatching(Class<? extends Postman> clazz);

    /**
     * 返回一个捕获重定向的Postman代理，使用默认实现类。
     *
     * @return Postman代理
     */
    default Postman withRedirectCatching() {
        return withRedirectCatching(null);
    }
}